package com.personal.core.utils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;

/**
 * Spring 字符串工具类
 * @author Spring
 *
 */
public abstract class StringUtil
{
    public static String applyRelativePath(String path, String relativePath)
    {
        int separatorIndex = path.lastIndexOf("/");
        if (separatorIndex != -1)
        {
            String newPath = path.substring(0, separatorIndex);
            if (!relativePath.startsWith("/"))
            {
                newPath = newPath + "/";
            }
            return newPath + relativePath;
        }

        return relativePath;
    }

    public static String capitalize(String str)
    {
        return StringUtil.changeFirstCharacterCase(str, true);
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static Set<String> commaDelimitedListToSet(String str)
    {
        Set set = new TreeSet();
        String[] tokens = StringUtil.commaDelimitedListToStringArray(str);
        for (String token : tokens)
        {
            set.add(token);
        }
        return set;
    }

    public static String[] commaDelimitedListToStringArray(String str)
    {
        return StringUtil.delimitedListToStringArray(str, ",");
    }

    public static boolean containsWhitespace(CharSequence str)
    {
        if (!StringUtil.hasLength(str))
        {
            return false;
        }
        int strLen = str.length();
        for (int i = 0; i < strLen; i++)
        {
            if (Character.isWhitespace(str.charAt(i)))
            {
                return true;
            }
        }
        return false;
    }

    public static boolean containsWhitespace(String str)
    {
        return StringUtil.containsWhitespace(str);
    }

    public static int countOccurrencesOf(String str, String sub)
    {
        if (str == null || sub == null || str.length() == 0 || sub.length() == 0)
        {
            return 0;
        }
        int count = 0;
        int pos = 0;
        int idx;
        while ((idx = str.indexOf(sub, pos)) != -1)
        {
            count++;
            pos = idx + sub.length();
        }
        return count;
    }

    public static String delete(String inString, String pattern)
    {
        return StringUtil.replace(inString, pattern, "");
    }

    public static String deleteAny(String inString, String charsToDelete)
    {
        if (!StringUtil.hasLength(inString) || !StringUtil.hasLength(charsToDelete))
        {
            return inString;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < inString.length(); i++)
        {
            char c = inString.charAt(i);
            if (charsToDelete.indexOf(c) == -1)
            {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    public static String[] delimitedListToStringArray(String str, String delimiter)
    {
        return StringUtil.delimitedListToStringArray(str, delimiter, null);
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static String[] delimitedListToStringArray(String str, String delimiter, String charsToDelete)
    {
        if (str == null)
        {
            return new String[0];
        }
        if (delimiter == null)
        {
            return new String[]
            { str };
        }
        List result = new ArrayList();
        if ("".equals(delimiter))
        {
            for (int i = 0; i < str.length(); i++)
            {
                result.add(StringUtil.deleteAny(str.substring(i, i + 1), charsToDelete));
            }
        } else
        {
            int pos = 0;
            int delPos;
            while ((delPos = str.indexOf(delimiter, pos)) != -1)
            {
                result.add(StringUtil.deleteAny(str.substring(pos, delPos), charsToDelete));
                pos = delPos + delimiter.length();
            }
            if (str.length() > 0 && pos <= str.length())
            {
                result.add(StringUtil.deleteAny(str.substring(pos), charsToDelete));
            }
        }
        return StringUtil.toStringArray(result);
    }

    public static boolean endsWithIgnoreCase(String str, String suffix)
    {
        if (str == null || suffix == null)
        {
            return false;
        }
        if (str.endsWith(suffix))
        {
            return true;
        }
        if (str.length() < suffix.length())
        {
            return false;
        }

        String lcStr = str.substring(str.length() - suffix.length()).toLowerCase();
        String lcSuffix = suffix.toLowerCase();
        return lcStr.equals(lcSuffix);
    }

    public static String getFilename(String path)
    {
        if (path == null)
        {
            return null;
        }
        int separatorIndex = path.lastIndexOf("/");
        return separatorIndex != -1 ? path.substring(separatorIndex + 1) : path;
    }

    public static String getFilenameExtension(String path)
    {
        if (path == null)
        {
            return null;
        }
        int extIndex = path.lastIndexOf('.');
        if (extIndex == -1)
        {
            return null;
        }
        int folderIndex = path.lastIndexOf("/");
        if (folderIndex > extIndex)
        {
            return null;
        }
        return path.substring(extIndex + 1);
    }

    public static boolean hasLength(CharSequence str)
    {
        return str != null && str.length() > 0;
    }

    public static boolean hasLength(String str)
    {
        return str != null && str.length() > 0;
    }

    public static boolean hasText(CharSequence str)
    {
        if (!StringUtil.hasLength(str))
        {
            return false;
        }
        int strLen = str.length();
        for (int i = 0; i < strLen; i++)
        {
            if (!Character.isWhitespace(str.charAt(i)))
            {
                return true;
            }
        }
        return false;
    }

    public static boolean hasText(String str)
    {
        return StringUtil.hasText(str);
    }

    public static boolean isEmpty(Object str)
    {
        return str == null || "".equals(str);
    }

    public static Locale parseLocaleString(String localeString)
    {
        String[] parts = StringUtil.tokenizeToStringArray(localeString, "_ ", false, false);
        String language = parts.length > 0 ? parts[0] : "";
        String country = parts.length > 1 ? parts[1] : "";
        StringUtil.validateLocalePart(language);
        StringUtil.validateLocalePart(country);
        String variant = "";
        if (parts.length >= 2)
        {
            int endIndexOfCountryCode = localeString.lastIndexOf(country) + country.length();

            variant = StringUtil.trimLeadingWhitespace(localeString.substring(endIndexOfCountryCode));
            if (variant.startsWith("_"))
            {
                variant = StringUtil.trimLeadingCharacter(variant, '_');
            }
        }
        return language.length() > 0 ? new Locale(language, country, variant) : null;
    }

    public static String quote(String str)
    {
        return str != null ? "'" + str + "'" : null;
    }

    public static Object quoteIfString(Object obj)
    {
        return obj instanceof String ? StringUtil.quote((String) obj) : obj;
    }

    public static String replace(String inString, String oldPattern, String newPattern)
    {
        if (!StringUtil.hasLength(inString) || !StringUtil.hasLength(oldPattern) || newPattern == null)
        {
            return inString;
        }
        StringBuilder sb = new StringBuilder();
        int pos = 0;
        int index = inString.indexOf(oldPattern);

        int patLen = oldPattern.length();
        while (index >= 0)
        {
            sb.append(inString.substring(pos, index));
            sb.append(newPattern);
            pos = index + patLen;
            index = inString.indexOf(oldPattern, pos);
        }
        sb.append(inString.substring(pos));

        return sb.toString();
    }
    
    public static String replaceFirst(String inString, String oldPattern, String newPattern)
    {
        if (!StringUtil.hasLength(inString) || !StringUtil.hasLength(oldPattern) || newPattern == null)
        {
            return inString;
        }
        int index = inString.indexOf(oldPattern);

        if (index >= 0)
        {
            StringBuilder sb = new StringBuilder();
            sb.append(inString.substring(0, index));
            sb.append(newPattern);
            sb.append(inString.substring(index + oldPattern.length(), inString.length()));
            return sb.toString();
        } else
        {
            return inString;
        }
    }

    public static String[] split(String toSplit, String delimiter)
    {
        if (!StringUtil.hasLength(toSplit) || !StringUtil.hasLength(delimiter))
        {
            return null;
        }
        int offset = toSplit.indexOf(delimiter);
        if (offset < 0)
        {
            return null;
        }
        String beforeDelimiter = toSplit.substring(0, offset);
        String afterDelimiter = toSplit.substring(offset + delimiter.length());
        return new String[]
        { beforeDelimiter, afterDelimiter };
    }

    public static boolean startsWithIgnoreCase(String str, String prefix)
    {
        if (str == null || prefix == null)
        {
            return false;
        }
        if (str.startsWith(prefix))
        {
            return true;
        }
        if (str.length() < prefix.length())
        {
            return false;
        }
        String lcStr = str.substring(0, prefix.length()).toLowerCase();
        String lcPrefix = prefix.toLowerCase();
        return lcStr.equals(lcPrefix);
    }

    public static String stripFilenameExtension(String path)
    {
        if (path == null)
        {
            return null;
        }
        int extIndex = path.lastIndexOf('.');
        if (extIndex == -1)
        {
            return path;
        }
        int folderIndex = path.lastIndexOf("/");
        if (folderIndex > extIndex)
        {
            return path;
        }
        return path.substring(0, extIndex);
    }

    public static boolean substringMatch(CharSequence str, int index, CharSequence substring)
    {
        for (int j = 0; j < substring.length(); j++)
        {
            int i = index + j;
            if (i >= str.length() || str.charAt(i) != substring.charAt(j))
            {
                return false;
            }
        }
        return true;
    }

    public static String[] tokenizeToStringArray(String str, String delimiters)
    {
        return StringUtil.tokenizeToStringArray(str, delimiters, true, true);
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static String[] tokenizeToStringArray(String str, String delimiters, boolean trimTokens,
            boolean ignoreEmptyTokens)
    {
        if (str == null)
        {
            return null;
        }
        StringTokenizer st = new StringTokenizer(str, delimiters);
        List tokens = new ArrayList();
        while (st.hasMoreTokens())
        {
            String token = st.nextToken();
            if (trimTokens)
            {
                token = token.trim();
            }
            if (!ignoreEmptyTokens || token.length() > 0)
            {
                tokens.add(token);
            }
        }
        return StringUtil.toStringArray(tokens);
    }

    public static String toLanguageTag(Locale locale)
    {
        return locale.getLanguage() + (StringUtil.hasText(locale.getCountry()) ? "-" + locale.getCountry() : "");
    }

    public static String[] toStringArray(Collection<String> collection)
    {
        if (collection == null)
        {
            return null;
        }
        return collection.toArray(new String[collection.size()]);
    }

    @SuppressWarnings("unchecked")
    public static String[] toStringArray(Enumeration<String> enumeration)
    {
        if (enumeration == null)
        {
            return null;
        }
        @SuppressWarnings("rawtypes")
        List list = Collections.list(enumeration);
        return (String[]) list.toArray(new String[list.size()]);
    }

    public static String trimAllWhitespace(String str)
    {
        if (!StringUtil.hasLength(str))
        {
            return str;
        }
        StringBuilder sb = new StringBuilder(str);
        int index = 0;
        while (sb.length() > index)
        {
            if (Character.isWhitespace(sb.charAt(index)))
            {
                sb.deleteCharAt(index);
            } else
            {
                index++;
            }
        }
        return sb.toString();
    }

    public static String trimLeadingCharacter(String str, char leadingCharacter)
    {
        if (!StringUtil.hasLength(str))
        {
            return str;
        }
        StringBuilder sb = new StringBuilder(str);
        while (sb.length() > 0 && sb.charAt(0) == leadingCharacter)
        {
            sb.deleteCharAt(0);
        }
        return sb.toString();
    }

    public static String trimLeadingWhitespace(String str)
    {
        if (!StringUtil.hasLength(str))
        {
            return str;
        }
        StringBuilder sb = new StringBuilder(str);
        while (sb.length() > 0 && Character.isWhitespace(sb.charAt(0)))
        {
            sb.deleteCharAt(0);
        }
        return sb.toString();
    }

    public static String trimTrailingCharacter(String str, char trailingCharacter)
    {
        if (!StringUtil.hasLength(str))
        {
            return str;
        }
        StringBuilder sb = new StringBuilder(str);
        while (sb.length() > 0 && sb.charAt(sb.length() - 1) == trailingCharacter)
        {
            sb.deleteCharAt(sb.length() - 1);
        }
        return sb.toString();
    }

    public static String trimTrailingWhitespace(String str)
    {
        if (!StringUtil.hasLength(str))
        {
            return str;
        }
        StringBuilder sb = new StringBuilder(str);
        while (sb.length() > 0 && Character.isWhitespace(sb.charAt(sb.length() - 1)))
        {
            sb.deleteCharAt(sb.length() - 1);
        }
        return sb.toString();
    }

    public static String trimWhitespace(String str)
    {
        if (!StringUtil.hasLength(str))
        {
            return str;
        }
        StringBuilder sb = new StringBuilder(str);
        while (sb.length() > 0 && Character.isWhitespace(sb.charAt(0)))
        {
            sb.deleteCharAt(0);
        }
        while (sb.length() > 0 && Character.isWhitespace(sb.charAt(sb.length() - 1)))
        {
            sb.deleteCharAt(sb.length() - 1);
        }
        return sb.toString();
    }

    public static String uncapitalize(String str)
    {
        return StringUtil.changeFirstCharacterCase(str, false);
    }

    public static String unqualify(String qualifiedName)
    {
        return StringUtil.unqualify(qualifiedName, '.');
    }

    public static String unqualify(String qualifiedName, char separator)
    {
        return qualifiedName.substring(qualifiedName.lastIndexOf(separator) + 1);
    }

    private static String changeFirstCharacterCase(String str, boolean capitalize)
    {
        if (str == null || str.length() == 0)
        {
            return str;
        }
        StringBuilder sb = new StringBuilder(str.length());
        if (capitalize)
        {
            sb.append(Character.toUpperCase(str.charAt(0)));
        } else
        {
            sb.append(Character.toLowerCase(str.charAt(0)));
        }
        sb.append(str.substring(1));
        return sb.toString();
    }

    private static void validateLocalePart(String localePart)
    {
        for (int i = 0; i < localePart.length(); i++)
        {
            char ch = localePart.charAt(i);
            if (ch != '_' && ch != ' ' && !Character.isLetterOrDigit(ch))
            {
                throw new IllegalArgumentException("Locale part \"" + localePart + "\" contains invalid characters");
            }
        }
    }

}